<?php
/**
 * @license http://www.gnu.org/licenses/gpl.html GNU GPL, version 3 or later
 * @package FrontPress
 * @subpackage Thing
 */

/**
 * Internal class to return an array of FP_Thing. Works like an
 * array, but also allows mass variable setting/getting, saving,
 * and deleting.
 *
 * @since   2010-07-27-r7
 * @version $Id: class.fp-things.php 50 2010-08-03 20:34:20Z Nightgunner5 $
 */
class FP_Things implements ArrayAccess, Iterator, Countable {
	private $things;
	private $pos;
	var $total_found_rows;

	/**
	 * Create a new FP_Things object.
	 *
	 * @internal
	 * @param array $things an array of FP_Thing for this object to represent
	 * @param int $total_found_rows the total number of rows found for the
	 *                              query used to retrieve the data
	 */
	function __construct( $things, $total_found_rows ) {
		$this->things = (array) $things;
		$this->pos = 0;
		$this->total_found_rows = $total_found_rows;
	}

	function __isset( $name ) {
		return isset( $this->things[0]->$name );
	}

	function __get( $name ) {
		$return = array();
		foreach ( $this->things as $thing ) {
			$return[$thing->{$thing->get_id_field()}] = $thing->$name;
		}
		return $return;
	}

	function __set( $name, $value ) {
		foreach ( $this->things as $thing ) {
			$thing->$name = $value;
		}
	}

	/**
	 * Save every FP_Thing in this object to the database
	 *
	 * @return int the total number of rows changed
	 */
	function save() {
		$num = 0;
		foreach ( $this->things as $thing ) {
			$num += $thing->save();
		}
		return $num;
	}

	/**
	 * Delete every FP_Thing in this object from the database
	 *
	 * @return int the total number of rows deleted
	 */
	function delete() {
		$num = 0;
		foreach ( $this->things as $thing ) {
			$num += $thing->delete();
		}
		return $num;
	}

	function filter( $key, $val ) {
		if ( is_a( $val, 'FP_Thing' ) || is_a( $val, 'FP_Things' ) ) {
			if ( isset( $this->things[0]->$key ) && isset( $val->{$val->get_id_field()} ) ) {
				$val = $val->{$val->get_id_field()};
			} elseif ( isset( $this->things[0]->{$key . '_id'} ) && isset( $val->{$val->get_id_field()} ) ) {
				$val = $val->{$val->get_id_field()};
				$key .= '_id';
			} elseif ( isset( $this->things[0]->{$key . '_slug'} ) && isset( $val->{$val->get_id_field()} ) ) {
				$val = $val->{$val->get_id_field()};
				$key .= '_slug';
			}
		}

		$things = array();
		if ( is_array( $val ) ) {
			foreach ( $this->things as $thing ) {
				if ( in_array( $thing->$key, $val ) )
					$things[] = $thing;
			}
		} else {
			foreach ( $this->things as $thing ) {
				if ( $thing->$key == $val )
					$things[] = $thing;
			}
		}
		return new FP_Things( $things, $this->total_found_rows );
	}

	function filter_not( $key, $val ) {
		if ( is_a( $val, 'FP_Thing' ) || is_a( $val, 'FP_Things' ) ) {
			if ( isset( $this->things[0]->$key ) && isset( $val->{$val->get_id_field()} ) ) {
				$val = $val->{$val->get_id_field()};
			} elseif ( isset( $this->things[0]->{$key . '_id'} ) && isset( $val->{$val->get_id_field()} ) ) {
				$val = $val->{$val->get_id_field()};
				$key .= '_id';
			} elseif ( isset( $this->things[0]->{$key . '_slug'} ) && isset( $val->{$val->get_id_field()} ) ) {
				$val = $val->{$val->get_id_field()};
				$key .= '_slug';
			}
		}
		$val = (array) $val;

		$things = array();
		foreach ( $this->things as $thing ) {
			if ( !in_array( $thing->$key, $val ) )
				$things[] = $thing;
		}
		return new FP_Things( $things, $this->total_found_rows );
	}

	function filter_like( $key, $val ) {
		$regexp = '/^(?:' . str_replace( array( '%', '\\\\.*', '_', '\\\\(?:.)', md5( serialize( $val ) ) ), array( '.*', '%', '(?:.)', '_', '|' ), preg_quote( implode( md5( serialize( $val ) ), (array) $val ), '/' ) ) . ')$/iS';

		$things = array();
		foreach ( $this->things as $thing ) {
			if ( preg_match( $regexp, $thing->$key ) )
				$things[] = $thing;
		}
		return new FP_Things( $things, $this->total_found_rows );
	}

	function filter_not_like( $key, $val ) {
		$regexp = '/^(?:' . str_replace( array( '%', '\\\\.*', '_', '\\\\(?:.)', md5( serialize( $val ) ) ), array( '.*', '%', '(?:.)', '_', '|' ), preg_quote( implode( md5( serialize( $val ) ), (array) $val ), '/' ) ) . ')$/iS';

		$things = array();
		foreach ( $this->things as $thing ) {
			if ( !preg_match( $regexp, $thing->$key ) )
				$things[] = $thing;
		}
		return new FP_Things( $things, $this->total_found_rows );
	}

	function get_values() {
		$return = array();
		foreach ( $this->things as $thing ) {
			$return[$thing->id ? $thing->id : $thing->slug] = $thing->get_values();
		}
		return $return;
	}

	function sort( $callback ) {
		usort( $this->things, $callback );
	}

	function set( $key, $val ) {
		foreach ( $this->things as $thing ) {
			$thing->$key = $val;
		}
		return $this;
	}

	function get() {
		return $this->things;
	}

	/**#@+
	 * ArrayAccess
	 *
	 * @internal
	 */
	function offsetExists( $offset ) {
		return isset( $this->things[$offset] );
	}

	function offsetGet( $offset ) {
		return $this->things[$offset];
	}

	function offsetSet( $offset, $value ) {
		if ( is_null( $offset ) )
		$this->things[] = $value;
		else
		$this->things[$offset] = $value;
	}

	function offsetUnset( $offset ) {
		unset( $this->things[$offset] );
	}
	/**#@-*/

	/**#@+
	 * Iterator
	 *
	 * @internal
	 */
	function current() {
		return $this->things[$this->pos];
	}

	function key() {
		return $this->pos;
	}

	function next() {
		$this->pos++;
	}

	function rewind() {
		$this->pos = 0;
	}

	function valid() {
		return array_key_exists( $this->pos, $this->things );
	}
	/**#@-*/


	/**#@+
	 * Countable
	 *
	 * @internal
	 */
	function count() {
		return count( $this->things );
	}
	/**#@-*/
}